﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.Issues.ExtortionByDesertersIssueBehavior
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using Helpers;
using System;
using System.Collections.Generic;
using System.Linq;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.ComponentInterfaces;
using TaleWorlds.CampaignSystem.Conversation;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.Extensions;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.Map;
using TaleWorlds.CampaignSystem.MapEvents;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.CampaignSystem.Party.PartyComponents;
using TaleWorlds.CampaignSystem.Roster;
using TaleWorlds.CampaignSystem.Settlements;
using TaleWorlds.Core;
using TaleWorlds.Library;
using TaleWorlds.Localization;
using TaleWorlds.ObjectSystem;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem.Issues
{
  public class ExtortionByDesertersIssueBehavior : CampaignBehaviorBase
  {
    private const IssueBase.IssueFrequency ExtortionByDesertersIssueFrequency = IssueBase.IssueFrequency.Common;

    private void OnCheckForIssue(Hero hero)
    {
      if (this.ConditionsHold(hero))
        Campaign.Current.IssueManager.AddPotentialIssueData(hero, new PotentialIssueData(new PotentialIssueData.StartIssueDelegate(this.OnIssueSelected), typeof (ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssue), IssueBase.IssueFrequency.Common));
      else
        Campaign.Current.IssueManager.AddPotentialIssueData(hero, new PotentialIssueData(typeof (ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssue), IssueBase.IssueFrequency.Common));
    }

    private IssueBase OnIssueSelected(in PotentialIssueData pid, Hero issueOwner)
    {
      return (IssueBase) new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssue(issueOwner);
    }

    private bool ConditionsHold(Hero issueGiver)
    {
      if (issueGiver.IsHeadman)
      {
        Settlement currentSettlement = issueGiver.CurrentSettlement;
        if (currentSettlement.IsVillage && currentSettlement.Culture != null)
        {
          Town town = currentSettlement.Village.Bound?.Town;
          if (town != null)
            return (double) town.Security <= 50.0;
        }
      }
      return false;
    }

    public override void RegisterEvents()
    {
      CampaignEvents.OnCheckForIssueEvent.AddNonSerializedListener((object) this, new Action<Hero>(this.OnCheckForIssue));
    }

    public override void SyncData(IDataStore dataStore)
    {
    }

    public class ExtortionByDesertersIssue : IssueBase
    {
      internal const int IssuePreConditionMaxSecurityLevel = 50;
      internal const int IssueStayAliveConditionMaxSecurityLevel = 80;
      internal const float IssuePreConditionMinPlayerRelation = -10f;
      internal const int MinimumRequiredMenCount = 20;
      internal const int IssueDuration = 15;
      internal const int QuestTimeLimit = 12;
      internal const int AlternativeSolutionTroopTierRequirement = 2;
      private const int AlternativeSolutionRangedSkillThreshold = 150;
      private const int AlternativeSolutionEngineeringSkillThreshold = 120;
      private const int AlternativeSolutionHonorRewardOnSuccess = 60;
      private const int AlternativeSolutionHonorPenaltyOnFail = -20;
      private const int AlternativeSolutionRelationRewardOnSuccess = 8;
      private const int AlternativeSolutionRelationPenaltyOnFail = -10;
      private const int AlternativeSolutionIssueOwnerPowerBonusOnSuccess = 15;
      private const int AlternativeSolutionIssueOwnerPowerPenaltyOnFail = -10;
      private const int AlternativeSolutionTownSecurityBonusOnSuccess = 10;
      private const int AlternativeSolutionTownSecurityPenaltyOnFail = -10;
      private const int AlternativeSolutionTownProsperityBonusOnSuccess = 100;
      private const int AlternativeSolutionTownProsperityPenaltyOnFail = -50;
      private const int AlternativeSolutionPlayerRenownBonusOnSuccess = 2;

      internal static void AutoGeneratedStaticCollectObjectsExtortionByDesertersIssue(
        object o,
        List<object> collectedObjects)
      {
        ((MBObjectBase) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        base.AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      public override IssueBase.AlternativeSolutionScaleFlag AlternativeSolutionScaleFlags
      {
        get
        {
          return IssueBase.AlternativeSolutionScaleFlag.Casualties | IssueBase.AlternativeSolutionScaleFlag.FailureRisk;
        }
      }

      protected override int CompanionSkillRewardXP
      {
        get => (int) (800.0 + 1000.0 * (double) this.IssueDifficultyMultiplier);
      }

      public override TextObject IssueBriefByIssueGiver
      {
        get
        {
          TextObject parent = new TextObject("{=NhDEwaab}Well, if you know how to fight... Yes, we could use help. A group of deserters is camped out near here. They come every few weeks, demanding food and money. They've killed two villagers who resisted them. We asked our {?LORD.GENDER}mistress{?}lord{\\?}, {LORD.NAME}, for help but {?LORD.GENDER}her{?}his{\\?} men never get here in time.[if:convo_stern][ib:closed]");
          StringHelpers.SetCharacterProperties("LORD", this.IssueSettlement.OwnerClan.Leader.CharacterObject, parent);
          if (this.IssueSettlement.OwnerClan.Leader == Hero.MainHero)
            parent = new TextObject("{=dYO8piOM}Yes, my {?PLAYER.GENDER}lady{?}lord{\\?}. It is good of you to ask. A group of deserters is camped out near here. They come every few weeks, demanding food and money. They've killed two villagers who resisted them.[if:convo_stern][ib:closed]");
          return parent;
        }
      }

      public override TextObject IssueAcceptByPlayer
      {
        get => new TextObject("{=WO3EaqB3}How can I help you?");
      }

      public override TextObject IssueQuestSolutionExplanationByIssueGiver
      {
        get
        {
          return new TextObject("{=tb0gqxDZ}Here's the plan. We lay an ambush in the village. When they show up, we spring. If you join us, I think we've got a good chance of ridding ourselves of this scourge before they murder us one by one.[if:convo_stern][ib:normal]");
        }
      }

      public override TextObject IssueQuestSolutionAcceptByPlayer
      {
        get => new TextObject("{=vKxiFQRA}All right. I'll wait here and join you in your fight.");
      }

      public override TextObject IssueAlternativeSolutionSuccessLog
      {
        get
        {
          TextObject to = new TextObject("{=CLvxAzyV}Following your orders, {COMPANION.LINK} and your men has defeated the deserters and saved the people of {SETTLEMENT}.");
          to.SetTextVariable("SETTLEMENT", this.IssueSettlement.EncyclopediaLinkWithName);
          to.SetCharacterProperties("COMPANION", this.AlternativeSolutionHero.CharacterObject);
          return to;
        }
      }

      public override bool IsThereAlternativeSolution => true;

      public override int AlternativeSolutionBaseNeededMenCount
      {
        get => 21 + MathF.Ceiling(25f * this.IssueDifficultyMultiplier);
      }

      protected override int AlternativeSolutionBaseDurationInDaysInternal
      {
        get => 3 + MathF.Ceiling(5f * this.IssueDifficultyMultiplier);
      }

      protected override int RewardGold
      {
        get => 800 + MathF.Ceiling(4200f * this.IssueDifficultyMultiplier);
      }

      public override TextObject IssueAlternativeSolutionExplanationByIssueGiver
      {
        get
        {
          TextObject explanationByIssueGiver = new TextObject("{=J0Clb1RD}If you don't have the time, at least send one of your best companions with {TROOP_COUNT} experienced men for {RETURN_DAYS} days.[if:convo_stern][ib:closed]");
          explanationByIssueGiver.SetTextVariable("TROOP_COUNT", this.GetTotalAlternativeSolutionNeededMenCount());
          explanationByIssueGiver.SetTextVariable("RETURN_DAYS", this.GetTotalAlternativeSolutionDurationInDays());
          return explanationByIssueGiver;
        }
      }

      public override TextObject IssueAlternativeSolutionAcceptByPlayer
      {
        get
        {
          return new TextObject("{=A4oWozvO}I don't have time for this, but my companion and my men will wait here with you.");
        }
      }

      public override TextObject IssueDiscussAlternativeSolution
      {
        get
        {
          return new TextObject("{=YwMMZFSm}We're working with your men to plan the ambush, {?PLAYER.GENDER}madam{?}sir{\\?}. These thieves will regret the day they ever thought we were easy pickings.");
        }
      }

      public override TextObject IssueAlternativeSolutionResponseByIssueGiver
      {
        get => new TextObject("{=OLcbuZSa}Thank you. Your help is much appreciated.");
      }

      protected override TextObject AlternativeSolutionStartLog
      {
        get
        {
          TextObject parent = new TextObject("{=MTVhHmbb}{ISSUE_GIVER.LINK} told you that a group of deserters have been raiding their village regularly. You asked your companion {COMPANION.LINK} to take {TROOP_COUNT} men to stay with {ISSUE_GIVER.LINK} and defend the people of {ISSUE_SETTLEMENT}.");
          StringHelpers.SetCharacterProperties("ISSUE_GIVER", this.IssueOwner.CharacterObject, parent);
          StringHelpers.SetCharacterProperties("COMPANION", this.AlternativeSolutionHero.CharacterObject, parent);
          parent.SetTextVariable("ISSUE_SETTLEMENT", this.IssueSettlement.Name);
          parent.SetTextVariable("TROOP_COUNT", this.AlternativeSolutionSentTroops.TotalManCount - 1);
          return parent;
        }
      }

      public override bool IsThereLordSolution => false;

      public override bool DoTroopsSatisfyAlternativeSolution(
        TroopRoster troopRoster,
        out TextObject explanation)
      {
        explanation = TextObject.Empty;
        return QuestHelper.CheckRosterForAlternativeSolution(troopRoster, this.GetTotalAlternativeSolutionNeededMenCount(), ref explanation, 2);
      }

      public override bool AlternativeSolutionCondition(out TextObject explanation)
      {
        explanation = TextObject.Empty;
        return QuestHelper.CheckRosterForAlternativeSolution(MobileParty.MainParty.MemberRoster, this.GetTotalAlternativeSolutionNeededMenCount(), ref explanation, 2);
      }

      public override bool IsTroopTypeNeededByAlternativeSolution(CharacterObject character)
      {
        return character.Tier >= 2;
      }

      protected override void AlternativeSolutionEndWithSuccessConsequence()
      {
        this.RelationshipChangeWithIssueOwner = 8;
        this.IssueOwner.AddPower(15f);
        this.IssueSettlement.Village.Bound.Town.Security += 10f;
        this.IssueSettlement.Village.Bound.Town.Prosperity += 100f;
        TraitLevelingHelper.OnIssueSolvedThroughQuest(this.IssueOwner, new Tuple<TraitObject, int>[1]
        {
          new Tuple<TraitObject, int>(DefaultTraits.Honor, 60)
        });
      }

      protected override void AlternativeSolutionEndWithFailureConsequence()
      {
        this.IssueSettlement.Village.Bound.Town.Security += -10f;
        this.IssueSettlement.Village.Bound.Town.Prosperity += -50f;
        this.RelationshipChangeWithIssueOwner = -10;
        this.IssueOwner.AddPower(-10f);
        TraitLevelingHelper.OnIssueFailed(this.IssueOwner, new Tuple<TraitObject, int>[1]
        {
          new Tuple<TraitObject, int>(DefaultTraits.Honor, -20)
        });
      }

      protected override void OnGameLoad()
      {
      }

      protected override void HourlyTick()
      {
      }

      protected override QuestBase GenerateIssueQuest(string questId)
      {
        return (QuestBase) new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest(questId, this.IssueOwner, this.IssueDifficultyMultiplier, this.RewardGold, CampaignTime.DaysFromNow(12f));
      }

      public override IssueBase.IssueFrequency GetFrequency() => IssueBase.IssueFrequency.Common;

      protected override bool CanPlayerTakeQuestConditions(
        Hero issueGiver,
        out IssueBase.PreconditionFlags flag,
        out Hero relationHero,
        out SkillObject skill)
      {
        flag = IssueBase.PreconditionFlags.None;
        skill = (SkillObject) null;
        relationHero = (Hero) null;
        if ((double) issueGiver.GetRelationWithPlayer() < -10.0)
        {
          relationHero = issueGiver;
          flag |= IssueBase.PreconditionFlags.Relation;
        }
        Settlement currentSettlement = issueGiver.CurrentSettlement;
        if (currentSettlement != null && FactionManager.IsAtWarAgainstFaction(currentSettlement.MapFaction, Hero.MainHero.MapFaction))
          flag |= IssueBase.PreconditionFlags.AtWar;
        if (MobileParty.MainParty.MemberRoster.TotalHealthyCount < 20)
          flag |= IssueBase.PreconditionFlags.NotEnoughTroops;
        return flag == IssueBase.PreconditionFlags.None;
      }

      protected override void CompleteIssueWithTimedOutConsequences()
      {
      }

      public override bool IssueStayAliveConditions()
      {
        return (double) this.IssueSettlement.Village.Bound.Town.Security <= 80.0 && !this.IssueOwner.CurrentSettlement.IsRaided && !this.IssueOwner.CurrentSettlement.IsUnderRaid;
      }

      public override TextObject Title
      {
        get
        {
          TextObject title = new TextObject("{=P2VNGJDa}Extortion by Deserters at {SETTLEMENT}");
          title.SetTextVariable("SETTLEMENT", this.IssueSettlement.Name);
          return title;
        }
      }

      public override TextObject Description
      {
        get
        {
          TextObject description = new TextObject("{=atk3PTae}Deserters are extorting from the villagers of {SETTLEMENT} and have killed several who resisted.");
          description.SetTextVariable("SETTLEMENT", this.IssueSettlement.Name);
          return description;
        }
      }

      public override TextObject IssueAsRumorInSettlement
      {
        get
        {
          TextObject parent = new TextObject("{=Fv8CKNU2}I hope {QUEST_GIVER.NAME} knows what {?QUEST_GIVER.GENDER}she's{?}he's{\\?} doing with that plan to get rid of the deserters.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.IssueOwner.CharacterObject, parent);
          return parent;
        }
      }

      public ExtortionByDesertersIssue(Hero issueOwner)
        : base(issueOwner, CampaignTime.DaysFromNow(15f))
      {
      }

      protected override float GetIssueEffectAmountInternal(IssueEffect issueEffect)
      {
        if (issueEffect == DefaultIssueEffects.SettlementProsperity || issueEffect == DefaultIssueEffects.SettlementSecurity)
          return -1f;
        return issueEffect == DefaultIssueEffects.SettlementLoyalty ? -0.5f : 0.0f;
      }

      public override (SkillObject, int) GetAlternativeSolutionSkill(Hero hero)
      {
        int skillValue1 = hero.GetSkillValue(DefaultSkills.Bow);
        int skillValue2 = hero.GetSkillValue(DefaultSkills.Crossbow);
        int skillValue3 = hero.GetSkillValue(DefaultSkills.Throwing);
        int skillValue4 = hero.GetSkillValue(DefaultSkills.Engineering);
        if (skillValue1 >= skillValue2 && skillValue1 >= skillValue3 && skillValue1 >= skillValue4)
          return (DefaultSkills.Bow, 150);
        if (skillValue2 >= skillValue3 && skillValue2 >= skillValue4)
          return (DefaultSkills.Crossbow, 150);
        return skillValue3 < skillValue4 ? (DefaultSkills.Engineering, 120) : (DefaultSkills.Throwing, 150);
      }
    }

    public class ExtortionByDesertersIssueQuest : QuestBase
    {
      private const float SightOffsetToLoseDeserterParty = 3f;
      private const float SightRatioToStartEvadingPlayerParty = 0.8f;
      [SaveableField(1)]
      private MobileParty _deserterMobileParty;
      [SaveableField(2)]
      private MobileParty _defenderMobileParty;
      [SaveableField(3)]
      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState _currentState;
      [SaveableField(4)]
      private readonly float _questDifficultyMultiplier;
      [SaveableField(5)]
      private bool _deserterBattleFinalizedForTheFirstTime;
      private bool _playerAwayFromSettlementNotificationSent;

      internal static void AutoGeneratedStaticCollectObjectsExtortionByDesertersIssueQuest(
        object o,
        List<object> collectedObjects)
      {
        ((MBObjectBase) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
      }

      protected override void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
      {
        base.AutoGeneratedInstanceCollectObjects(collectedObjects);
        collectedObjects.Add((object) this._deserterMobileParty);
        collectedObjects.Add((object) this._defenderMobileParty);
      }

      internal static object AutoGeneratedGetMemberValue_deserterMobileParty(object o)
      {
        return (object) ((ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest) o)._deserterMobileParty;
      }

      internal static object AutoGeneratedGetMemberValue_defenderMobileParty(object o)
      {
        return (object) ((ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest) o)._defenderMobileParty;
      }

      internal static object AutoGeneratedGetMemberValue_currentState(object o)
      {
        return (object) ((ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest) o)._currentState;
      }

      internal static object AutoGeneratedGetMemberValue_questDifficultyMultiplier(object o)
      {
        return (object) ((ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest) o)._questDifficultyMultiplier;
      }

      internal static object AutoGeneratedGetMemberValue_deserterBattleFinalizedForTheFirstTime(
        object o)
      {
        return (object) ((ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest) o)._deserterBattleFinalizedForTheFirstTime;
      }

      public override TextObject Title
      {
        get
        {
          TextObject title = new TextObject("{=vbiA31xT}Extortion by Deserters at {SETTLEMENT}");
          title.SetTextVariable("SETTLEMENT", this.QuestSettlement.Name);
          return title;
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultSuccess1
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, 20, 1f, 4, 5, 10, 0, true);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultSuccess2
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(1, 40, 0.5f, 6, 10, 10, 25, true);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultSuccess3
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(2, 60, 0.0f, 8, 15, 10, 100, true);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultFail1
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, -20, 0.0f, -10, -10, -10, -50, false);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultFail2
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, -20, 0.0f, -10, -10, -10, -50, false);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultFail3
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, -50, 0.0f, -5, -10, -10, -50, false);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultTimeOut
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, -20, 0.0f, -10, 0, 0, 0, false);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultCancel1
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, 0, 0.0f, 0, 0, 0, 0, false);
        }
      }

      private ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult _questResultCancel2
      {
        get
        {
          return new ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult(0, 0, 0.0f, 0, 0, 0, 0, false);
        }
      }

      private TextObject _onQuestStartedLogText
      {
        get
        {
          TextObject parent = new TextObject("{=pWxXvtXP}{QUEST_GIVER.LINK}, a headman of {QUEST_SETTLEMENT} told you that a group of deserters have been raiding their village regularly. {?QUEST_GIVER.GENDER}She{?}He{\\?} asked you to wait in {QUEST_SETTLEMENT} until the deserters arrive...");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          parent.SetTextVariable("QUEST_SETTLEMENT", this.QuestSettlement.EncyclopediaLinkWithName);
          return parent;
        }
      }

      private TextObject _onQuestSucceededLogText
      {
        get
        {
          TextObject succeededLogText = new TextObject("{=IXkgPlKR}You have defeated the deserters and saved the people of {QUEST_SETTLEMENT}.");
          succeededLogText.SetTextVariable("QUEST_SETTLEMENT", this.QuestSettlement.Name);
          return succeededLogText;
        }
      }

      private TextObject _onQuestFailed1LogText
      {
        get => new TextObject("{=bdWc1VEl}You've lost track of the deserter party.");
      }

      private TextObject _onQuestFailed2LogText
      {
        get
        {
          return new TextObject("{=oYJCP3mt}You've failed to stop the deserters. The deserters ravaged the village and left.");
        }
      }

      private TextObject _onQuestFailed3LogText
      {
        get
        {
          TextObject parent = new TextObject("{=GLuN0dZg}Your criminal action towards {QUEST_SETTLEMENT} has angered {QUEST_GIVER.LINK} and {?QUEST_GIVER.GENDER}she{?}he{\\?} broke off the agreement that you had.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          parent.SetTextVariable("QUEST_SETTLEMENT", this.QuestSettlement.EncyclopediaLinkWithName);
          return parent;
        }
      }

      private TextObject _onQuestTimedOutLogText
      {
        get
        {
          TextObject parent = new TextObject("{=YjxCkglX}You've failed to complete this quest in time. Your agreement with {QUEST_GIVER.LINK} was canceled.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _onQuestCancel1LogText
      {
        get
        {
          TextObject parent = new TextObject("{=x346Rqle}Your clan is now at war with the {QUEST_GIVER.LINK}'s lord. Your agreement was canceled.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _playerDeclaredWarQuestLogText
      {
        get
        {
          TextObject parent = new TextObject("{=bqeWVVEE}Your actions have started a war with {QUEST_GIVER.LINK}'s faction. {?QUEST_GIVER.GENDER}She{?}He{\\?} cancels your agreement and the quest is a failure.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _onQuestCancel2LogText
      {
        get
        {
          TextObject parent = new TextObject("{=wTx2MNIJ}{QUEST_SETTLEMENT} was raided. {QUEST_GIVER.LINK} can no longer fulfill your contract. Agreement was canceled.");
          parent.SetTextVariable("QUEST_SETTLEMENT", this.QuestSettlement.Name);
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _onDeserterPartyDefeatedLogText
      {
        get
        {
          TextObject parent = new TextObject("{=sRBvUj6U}The deserter party is defeated. Return back to {QUEST_GIVER.LINK} to claim your rewards.");
          StringHelpers.SetCharacterProperties("QUEST_GIVER", this.QuestGiver.CharacterObject, parent);
          return parent;
        }
      }

      private TextObject _onPlayerLeftQuestSettlementNotificationText
      {
        get
        {
          TextObject parent = new TextObject("{=qjuiWN4K}{PLAYER.NAME}, you should wait with us in the village to ambush the deserters!");
          StringHelpers.SetCharacterProperties("PLAYER", CharacterObject.PlayerCharacter, parent);
          return parent;
        }
      }

      private TextObject _onPlayerDefeatedDesertersNotificationText
      {
        get
        {
          TextObject parent = new TextObject("{=EfZaCzb0}{PLAYER.NAME}, please return back to {QUEST_SETTLEMENT} to claim your rewards.");
          StringHelpers.SetCharacterProperties("PLAYER", CharacterObject.PlayerCharacter, parent);
          parent.SetTextVariable("QUEST_SETTLEMENT", this.QuestSettlement.Name);
          return parent;
        }
      }

      private TextObject _onDesertersNoticedPlayerNotificationText
      {
        get
        {
          return new TextObject("{=9vzm2j5T}Deserters have noticed our presence, they are running away!");
        }
      }

      private DialogFlow QuestCompletionDialogFlow
      {
        get
        {
          return DialogFlow.CreateDialogFlow("start", 125).NpcLine("{=SCaWkKF1}Here is what we've promised, {GOLD_REWARD}{GOLD_ICON} denars. I hope this makes it worth the blood spilled.[if:convo_normal][ib:hip]").Condition((ConversationSentence.OnConditionDelegate) (() =>
          {
            MBTextManager.SetTextVariable("GOLD_REWARD", this.RewardGold);
            return Hero.OneToOneConversationHero == this.QuestGiver && this._currentState == ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersAreDefeated;
          })).BeginPlayerOptions().PlayerOption("{=Bb3oHQNa}Thanks, this will come in handy.").NpcLine("{=khIuyBAi}Thank you for your help. Farewell.").Consequence((ConversationSentence.OnConsequenceDelegate) (() =>
          {
            this.ApplyQuestResult(this._questResultSuccess1);
            this.AddLog(this._onQuestSucceededLogText);
            this.CompleteQuestWithSuccess();
          })).CloseDialog().PlayerOption("{=xcyr5Oq2}Half of the coin is enough for our needs.").NpcLine("{=SVrCpvpZ}Thank you {PLAYER.NAME}. Our people are grateful to you for what you have done today. Farewell.[if:convo_relaxed_happy]").Condition((ConversationSentence.OnConditionDelegate) (() => true)).Consequence((ConversationSentence.OnConsequenceDelegate) (() =>
          {
            this.ApplyQuestResult(this._questResultSuccess2);
            this.AddLog(this._onQuestSucceededLogText);
            this.CompleteQuestWithSuccess();
          })).CloseDialog().PlayerOption("{=52GFRUTE}Keep your coin, headman. Your people's blessings are enough.").NpcLine("{=1l5dKk1c}Oh, thank you {PLAYER.NAME}. You will always be remembered by our people. Farewell.[if:convo_merry]").Condition((ConversationSentence.OnConditionDelegate) (() => true)).Consequence((ConversationSentence.OnConsequenceDelegate) (() =>
          {
            this.ApplyQuestResult(this._questResultSuccess3);
            this.AddLog(this._onQuestSucceededLogText);
            this.CompleteQuestWithSuccess();
          })).CloseDialog().EndPlayerOptions().CloseDialog();
        }
      }

      private DialogFlow DeserterPartyAmbushedDialogFlow
      {
        get
        {
          return DialogFlow.CreateDialogFlow("start", 125).NpcLine("{=s2btPjJf}Who the hell are you? If you live in this village, you'd better rustle up some silver and wine. Look lively, eh?[if:convo_confused_annoyed][ib:warrior]").Condition((ConversationSentence.OnConditionDelegate) (() => this._deserterMobileParty != null && this._deserterMobileParty.IsActive && CharacterObject.OneToOneConversationCharacter == ConversationHelper.GetConversationCharacterPartyLeader(this._deserterMobileParty.Party) && (double) this._deserterMobileParty.Position2D.Distance(this.QuestSettlement.Position2D) <= 5.0)).PlayerLine("{=Pp3koSqA}This time you'll have to fight for it!").CloseDialog();
        }
      }

      private int DeserterPartyMenCount
      {
        get => 24 + MathF.Ceiling(24f * this._questDifficultyMultiplier);
      }

      private int DefenderPartyMenCount
      {
        get => 16 + MathF.Ceiling(16f * this._questDifficultyMultiplier);
      }

      public Settlement QuestSettlement => this.QuestGiver.CurrentSettlement;

      public override bool IsRemainingTimeHidden => false;

      public ExtortionByDesertersIssueQuest(
        string questId,
        Hero questGiver,
        float difficultyMultiplier,
        int rewardGold,
        CampaignTime duration)
        : base(questId, questGiver, duration, rewardGold)
      {
        StringHelpers.SetCharacterProperties("PLAYER", CharacterObject.PlayerCharacter);
        this._questDifficultyMultiplier = difficultyMultiplier;
        this._defenderMobileParty = (MobileParty) null;
        this._deserterBattleFinalizedForTheFirstTime = false;
        this._playerAwayFromSettlementNotificationSent = false;
        this.CreateDeserterParty();
        this._currentState = ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersMovingToSettlement;
        this.AddTrackedObject((ITrackableCampaignObject) this._deserterMobileParty);
        this.SetDialogs();
        this.InitializeQuestOnCreation();
      }

      protected override void InitializeQuestOnGameLoad()
      {
        StringHelpers.SetCharacterProperties("PLAYER", CharacterObject.PlayerCharacter);
        this._playerAwayFromSettlementNotificationSent = false;
        if (this._currentState == ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersMovingToSettlement)
        {
          double num1 = (double) this._deserterMobileParty.Position2D.Distance(MobileParty.MainParty.Position2D);
          bool flag1 = PlayerEncounter.Current != null && PlayerEncounter.EncounterSettlement == this.QuestSettlement;
          double num2 = (double) this._deserterMobileParty.SeeingRange * 0.800000011920929;
          bool flag2 = num1 <= num2;
          this._playerAwayFromSettlementNotificationSent = !flag1 && !flag2;
        }
        this.SetDialogs();
        Campaign.Current.ConversationManager.AddDialogFlow(this.QuestCompletionDialogFlow, (object) this);
        Campaign.Current.ConversationManager.AddDialogFlow(this.DeserterPartyAmbushedDialogFlow, (object) this);
      }

      protected override void SetDialogs()
      {
        this.OfferDialogFlow = DialogFlow.CreateDialogFlow("issue_classic_quest_start").NpcLine("{=PnRVabwv}Thank you. Just wait in the village. We'll stand lookout and lure them into your ambush. Just wait for the signal.").Condition((ConversationSentence.OnConditionDelegate) (() => Hero.OneToOneConversationHero == this.QuestGiver)).Consequence(new ConversationSentence.OnConsequenceDelegate(this.OnQuestAccepted)).CloseDialog();
        this.DiscussDialogFlow = DialogFlow.CreateDialogFlow("quest_discuss").NpcLine("{=iN1kBsac}I don't think they'll be long now. Our hunters have spotted them making ready. Keep waiting.").Condition((ConversationSentence.OnConditionDelegate) (() => Hero.OneToOneConversationHero == this.QuestGiver)).BeginPlayerOptions().PlayerOption("{=IJihRdfF}Don't worry, we'll be ready for the fight.").NpcLine("{=U0UoayfA}Good, good. Thank you again.").CloseDialog().PlayerOption("{=bcGzpFSg}Are you sure about what your hunters saw? My men are starting to run out of patience.").NpcLine("{=YsASaPKq}I'm sure they'll be here soon. Please don't leave the village, or we'll stand no chance...[if:convo_nervous][ib:nervous]").CloseDialog().EndPlayerOptions().CloseDialog();
        this.QuestCharacterDialogFlow = DialogFlow.CreateDialogFlow("start", 125).NpcLine("{=rAqyKcKZ}Who the hell are you? What do you want from us?[if:convo_confused_annoyed][ib:aggressive]").Condition((ConversationSentence.OnConditionDelegate) (() => this._deserterMobileParty != null && this._deserterMobileParty.IsActive && CharacterObject.OneToOneConversationCharacter == ConversationHelper.GetConversationCharacterPartyLeader(this._deserterMobileParty.Party) && (double) this._deserterMobileParty.Position2D.Distance(this.QuestSettlement.Position2D) >= 5.0)).BeginPlayerOptions().PlayerOption("{=Ljs9ahMk}I know your intentions. I will not let you steal from those poor villagers!").CloseDialog().EndPlayerOptions().CloseDialog();
      }

      private void OnQuestAccepted()
      {
        this.StartQuest();
        Campaign.Current.ConversationManager.AddDialogFlow(this.QuestCompletionDialogFlow, (object) this);
        Campaign.Current.ConversationManager.AddDialogFlow(this.DeserterPartyAmbushedDialogFlow, (object) this);
        this.AddLog(this._onQuestStartedLogText);
      }

      private void ApplyQuestResult(
        in ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestResult result)
      {
        int amount = (int) ((double) result.GoldMultiplier * (double) this.RewardGold);
        if (amount > 0)
          GiveGoldAction.ApplyBetweenCharacters((Hero) null, Hero.MainHero, amount);
        if (result.QuestGiverPowerChange != 0)
          this.QuestGiver.AddPower((float) result.QuestGiverPowerChange);
        if (result.TownSecurityChange != 0)
          this.QuestSettlement.Village.Bound.Town.Security += (float) result.TownSecurityChange;
        if (result.TownProsperityChange != 0)
          this.QuestSettlement.Village.Bound.Town.Prosperity += (float) result.TownProsperityChange;
        if (result.HonorChange != 0)
        {
          if (result.IsSuccess)
            TraitLevelingHelper.OnIssueSolvedThroughQuest(this.QuestGiver, new Tuple<TraitObject, int>[1]
            {
              new Tuple<TraitObject, int>(DefaultTraits.Honor, result.HonorChange)
            });
          else
            TraitLevelingHelper.OnIssueFailed(this.QuestGiver, new Tuple<TraitObject, int>[1]
            {
              new Tuple<TraitObject, int>(DefaultTraits.Honor, result.HonorChange)
            });
        }
        if (result.QuestGiverRelationChange != 0)
          this.RelationshipChangeWithQuestGiver = result.QuestGiverRelationChange;
        if (result.RenownChange <= 0)
          return;
        GainRenownAction.Apply(Hero.MainHero, (float) result.RenownChange);
      }

      protected override void RegisterEvents()
      {
        CampaignEvents.MapEventEnded.AddNonSerializedListener((object) this, new Action<MapEvent>(this.MapEventEnded));
        CampaignEvents.GameMenuOpened.AddNonSerializedListener((object) this, new Action<MenuCallbackArgs>(this.GameMenuOpened));
        CampaignEvents.WarDeclared.AddNonSerializedListener((object) this, new Action<IFaction, IFaction, DeclareWarAction.DeclareWarDetail>(this.OnWarDeclared));
        CampaignEvents.OnClanChangedKingdomEvent.AddNonSerializedListener((object) this, new Action<Clan, Kingdom, Kingdom, ChangeKingdomAction.ChangeKingdomActionDetail, bool>(this.OnClanChangedKingdom));
        CampaignEvents.SettlementEntered.AddNonSerializedListener((object) this, new Action<MobileParty, Settlement, Hero>(this.SettlementEntered));
        CampaignEvents.GameMenuOptionSelectedEvent.AddNonSerializedListener((object) this, new Action<GameMenuOption>(this.GameMenuOptionSelected));
        CampaignEvents.VillageBeingRaided.AddNonSerializedListener((object) this, new Action<Village>(this.OnVillageBeingRaided));
        CampaignEvents.MapEventStarted.AddNonSerializedListener((object) this, new Action<MapEvent, PartyBase, PartyBase>(this.OnMapEventStarted));
      }

      private void OnMapEventStarted(
        MapEvent mapEvent,
        PartyBase attackerParty,
        PartyBase defenderParty)
      {
        if (attackerParty != PartyBase.MainParty)
          return;
        if (mapEvent.IsFieldBattle && defenderParty.IsMobile && defenderParty.MobileParty.HomeSettlement == this.QuestSettlement)
        {
          this.CompleteQuestWithFail(this._onQuestFailed3LogText);
          this.ApplyQuestResult(this._questResultFail3);
        }
        else
        {
          if (!QuestHelper.CheckMinorMajorCoercion((QuestBase) this, mapEvent, attackerParty))
            return;
          QuestHelper.ApplyGenericMinorMajorCoercionConsequences((QuestBase) this, mapEvent);
        }
      }

      protected override void OnFinalize()
      {
        this.DestroyDefenderParty();
        this.ReleaseDeserterParty();
      }

      private void TickDesertersPartyLogic()
      {
        if ((this._deserterMobileParty == null ? 0 : (this._deserterMobileParty.MapEvent != null ? 1 : 0)) != 0 || !this.IsOngoing)
          return;
        switch (this._currentState)
        {
          case ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersMovingToSettlement:
            float num1 = this._deserterMobileParty.Position2D.Distance(MobileParty.MainParty.Position2D);
            int num2 = PlayerEncounter.Current == null ? 0 : (PlayerEncounter.EncounterSettlement == this.QuestSettlement ? 1 : 0);
            bool flag = (double) num1 <= (double) this._deserterMobileParty.SeeingRange * 0.800000011920929;
            if (num2 == 0)
            {
              if (flag)
              {
                MBInformationManager.AddQuickInformation(this._onDesertersNoticedPlayerNotificationText, announcerCharacter: (BasicCharacterObject) Hero.MainHero.CharacterObject);
                this.HandleDesertersRunningAway();
                this._currentState = ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersRunningAwayFromPlayer;
                break;
              }
              if (this._playerAwayFromSettlementNotificationSent)
                break;
              MBInformationManager.AddQuickInformation(this._onPlayerLeftQuestSettlementNotificationText, announcerCharacter: (BasicCharacterObject) this.QuestGiver.CharacterObject);
              this._playerAwayFromSettlementNotificationSent = true;
              break;
            }
            if (this._deserterMobileParty.IsCurrentlyGoingToSettlement)
              break;
            SetPartyAiAction.GetActionForVisitingSettlement(this._deserterMobileParty, this.QuestSettlement);
            break;
          case ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersRunningAwayFromPlayer:
            if ((double) this._deserterMobileParty.Position2D.Distance(MobileParty.MainParty.Position2D) > (double) MobileParty.MainParty.SeeingRange + 3.0)
            {
              this.ApplyQuestResult(this._questResultFail1);
              this.CompleteQuestWithFail(this._onQuestFailed1LogText);
              break;
            }
            this.HandleDesertersRunningAway();
            break;
          case ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersDefeatedPlayer:
            if (this._deserterMobileParty.IsCurrentlyGoingToSettlement)
              break;
            SetPartyAiAction.GetActionForVisitingSettlement(this._deserterMobileParty, this.QuestSettlement);
            break;
        }
      }

      protected override void HourlyTick() => this.TickDesertersPartyLogic();

      private void MapEventEnded(MapEvent mapEvent)
      {
        if (!mapEvent.IsPlayerMapEvent || this._deserterMobileParty == null || !mapEvent.InvolvedParties.Contains<PartyBase>(this._deserterMobileParty.Party))
          return;
        this._deserterBattleFinalizedForTheFirstTime = true;
        if (mapEvent.WinningSide == mapEvent.PlayerSide)
        {
          this.AddLog(this._onDeserterPartyDefeatedLogText);
          if (!this.IsTracked((ITrackableCampaignObject) this.QuestGiver))
            this.AddTrackedObject((ITrackableCampaignObject) this.QuestGiver);
          if (!this.IsTracked((ITrackableCampaignObject) this.QuestSettlement))
            this.AddTrackedObject((ITrackableCampaignObject) this.QuestSettlement);
          MBInformationManager.AddQuickInformation(this._onPlayerDefeatedDesertersNotificationText, announcerCharacter: (BasicCharacterObject) this.QuestGiver.CharacterObject);
          this._currentState = ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersAreDefeated;
        }
        else
        {
          if (!this._deserterMobileParty.IsCurrentlyGoingToSettlement)
            SetPartyAiAction.GetActionForVisitingSettlement(this._deserterMobileParty, this.QuestSettlement);
          this._currentState = ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersDefeatedPlayer;
        }
      }

      private void GameMenuOpened(MenuCallbackArgs mArgs)
      {
        if (!(mArgs.MenuContext.GameMenu.StringId == "encounter") || !this._deserterBattleFinalizedForTheFirstTime)
          return;
        this._deserterBattleFinalizedForTheFirstTime = false;
        if (this._currentState == ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersAreDefeated)
          this.DestroyDeserterParty();
        this.DestroyDefenderParty();
      }

      private void OnClanChangedKingdom(
        Clan clan,
        Kingdom oldKingdom,
        Kingdom newKingdom,
        ChangeKingdomAction.ChangeKingdomActionDetail detail,
        bool showNotification = true)
      {
        if (!this.QuestGiver.CurrentSettlement.MapFaction.IsAtWarWith(Hero.MainHero.MapFaction))
          return;
        this.CompleteQuestWithCancel(this._onQuestCancel1LogText);
        this.ApplyQuestResult(this._questResultCancel1);
      }

      private void OnWarDeclared(
        IFaction faction1,
        IFaction faction2,
        DeclareWarAction.DeclareWarDetail detail)
      {
        QuestHelper.CheckWarDeclarationAndFailOrCancelTheQuest((QuestBase) this, faction1, faction2, detail, this._playerDeclaredWarQuestLogText, this._onQuestCancel1LogText);
      }

      private void OnVillageBeingRaided(Village village)
      {
        if (village.Settlement != this.QuestSettlement)
          return;
        if (village.Settlement.Party.MapEvent.AttackerSide.LeaderParty == PartyBase.MainParty)
        {
          this.ApplyQuestResult(this._questResultFail3);
          this.CompleteQuestWithFail(this._onQuestFailed3LogText);
        }
        else
        {
          this.ApplyQuestResult(this._questResultCancel2);
          this.CompleteQuestWithCancel(this._onQuestCancel2LogText);
        }
      }

      private void SettlementEntered(MobileParty party, Settlement settlement, Hero hero)
      {
        if (party != this._deserterMobileParty || settlement != this.QuestSettlement)
          return;
        if (this._currentState != ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState.DesertersDefeatedPlayer & (PlayerEncounter.Current != null && PlayerEncounter.EncounterSettlement == this.QuestSettlement))
        {
          this.StartAmbushEncounter();
        }
        else
        {
          this.ApplyQuestResult(this._questResultFail2);
          this.CompleteQuestWithFail(this._onQuestFailed2LogText);
        }
      }

      private void GameMenuOptionSelected(GameMenuOption option)
      {
        if (!option.IsLeave)
          return;
        this.TickDesertersPartyLogic();
      }

      protected override void OnTimedOut()
      {
        this.ApplyQuestResult(this._questResultTimeOut);
        this.AddLog(this._onQuestTimedOutLogText);
      }

      private void CreateDeserterParty()
      {
        Settlement nearestHideout = SettlementHelper.FindNearestHideout();
        Clan clan = (Clan) null;
        if (nearestHideout != null)
        {
          CultureObject banditCulture = nearestHideout.Culture;
          clan = Clan.BanditFactions.FirstOrDefault<Clan>((Func<Clan, bool>) (x => x.Culture == banditCulture));
        }
        if (clan == null)
          clan = Clan.All.GetRandomElementWithPredicate<Clan>((Func<Clan, bool>) (x => x.IsBanditFaction));
        PartyTemplateObject defaultPartyTemplate = this.QuestSettlement.Culture.DefaultPartyTemplate;
        this._deserterMobileParty = BanditPartyComponent.CreateBanditParty("ebdi_deserters_party_1", clan, nearestHideout.Hideout, false);
        TextObject name = new TextObject("{=zT2b0v8y}Deserters Party");
        Vec2 forDeserterParty = this.FindBestSpawnPositionForDeserterParty();
        this._deserterMobileParty.InitializeMobilePartyAtPosition(defaultPartyTemplate, forDeserterParty, this.DeserterPartyMenCount);
        this._deserterMobileParty.SetCustomName(name);
        int number1 = 0;
        foreach (TroopRosterElement troopRosterElement in (List<TroopRosterElement>) this._deserterMobileParty.MemberRoster.GetTroopRoster())
        {
          if (!troopRosterElement.Character.HasMount())
            number1 += troopRosterElement.Number;
        }
        ItemObject itemObject = Items.All.GetRandomElementWithPredicate<ItemObject>((Func<ItemObject, bool>) (x => x.IsMountable && x.Culture == this.QuestSettlement.Culture && !x.NotMerchandise && x.Tier == ItemObject.ItemTiers.Tier2)) ?? MBObjectManager.Instance.GetObject<ItemObject>("vlandia_horse") ?? MBObjectManager.Instance.GetObject<ItemObject>("sumpter_horse");
        if (itemObject != null)
          this._deserterMobileParty.ItemRoster.AddToCounts(itemObject, number1);
        int num = MathF.Ceiling(this.QuestDueTime.RemainingDaysFromNow * MathF.Abs(this._deserterMobileParty.FoodChange));
        int number2 = num / 2;
        this._deserterMobileParty.ItemRoster.AddToCounts(DefaultItems.Grain, number2);
        this._deserterMobileParty.ItemRoster.AddToCounts(DefaultItems.Meat, num - number2);
        this._deserterMobileParty.SetPartyUsedByQuest(true);
        this._deserterMobileParty.IgnoreByOtherPartiesTill(CampaignTime.Never);
        this._deserterMobileParty.Aggressiveness = 0.0f;
        this._deserterMobileParty.Ai.SetDoNotMakeNewDecisions(true);
        this._deserterMobileParty.Party.SetVisualAsDirty();
        SetPartyAiAction.GetActionForVisitingSettlement(this._deserterMobileParty, this.QuestSettlement);
      }

      private Vec2 FindBestSpawnPositionForDeserterParty()
      {
        MobileParty mainParty = MobileParty.MainParty;
        Vec2 getPosition2D = mainParty.GetPosition2D;
        float seeingRange = mainParty.SeeingRange;
        float maxDistance = seeingRange + 3f;
        float num1 = maxDistance * 1.25f;
        float maximumDistance = num1 * 3f;
        Vec2 forDeserterParty = getPosition2D;
        float num2 = float.MaxValue;
        int num3 = 0;
        MapDistanceModel mapDistanceModel = Campaign.Current.Models.MapDistanceModel;
        do
        {
          Vec2 toPoint = MobilePartyHelper.FindReachablePointAroundPosition(getPosition2D, maxDistance, seeingRange);
          float distance;
          if (mapDistanceModel.GetDistance((IMapPoint) mainParty, in toPoint, maximumDistance, out distance))
          {
            if ((double) distance < (double) num2)
            {
              forDeserterParty = toPoint;
              num2 = distance;
            }
            if ((double) distance < (double) num1)
              break;
          }
          ++num3;
        }
        while (num3 < 16);
        return forDeserterParty;
      }

      private void DestroyDeserterParty()
      {
        if (this._deserterMobileParty == null || !this._deserterMobileParty.IsActive)
          return;
        DestroyPartyAction.Apply((PartyBase) null, this._deserterMobileParty);
        this._deserterMobileParty = (MobileParty) null;
      }

      private void ReleaseDeserterParty()
      {
        if (this._deserterMobileParty == null || !this._deserterMobileParty.IsActive)
          return;
        this._deserterMobileParty.SetPartyUsedByQuest(false);
        this._deserterMobileParty.IgnoreByOtherPartiesTill(CampaignTime.HoursFromNow(0.0f));
        this._deserterMobileParty.Aggressiveness = 1f;
        if (this._deserterMobileParty.CurrentSettlement != null)
          LeaveSettlementAction.ApplyForParty(this._deserterMobileParty);
        this._deserterMobileParty.Ai.SetDoNotMakeNewDecisions(false);
        this._deserterMobileParty.SetCustomName((TextObject) null);
        this._deserterMobileParty.Party.SetVisualAsDirty();
      }

      private void CreateDefenderParty()
      {
        PartyTemplateObject militiaPartyTemplate = this.QuestSettlement.Culture.MilitiaPartyTemplate;
        this._defenderMobileParty = MobileParty.CreateParty("ebdi_defender_party_1", (PartyComponent) null);
        TextObject name = new TextObject("{=dPU8UbKA}{QUEST_GIVER}'s Party");
        name.SetTextVariable("QUEST_GIVER", this.QuestGiver.Name);
        this._defenderMobileParty.InitializeMobilePartyAroundPosition(militiaPartyTemplate, this.QuestSettlement.GetPosition2D, 1f, 0.5f, this.DefenderPartyMenCount);
        this._defenderMobileParty.SetCustomName(name);
        this._defenderMobileParty.SetPartyUsedByQuest(true);
        this._defenderMobileParty.Party.SetCustomOwner(this.QuestGiver);
        this._defenderMobileParty.Aggressiveness = 1f;
        this._defenderMobileParty.ShouldJoinPlayerBattles = true;
        this._defenderMobileParty.ActualClan = this.QuestGiver.CurrentSettlement.OwnerClan;
      }

      private void DestroyDefenderParty()
      {
        if (this._defenderMobileParty == null || !this._defenderMobileParty.IsActive)
          return;
        DestroyPartyAction.Apply((PartyBase) null, this._defenderMobileParty);
        this._defenderMobileParty = (MobileParty) null;
      }

      private void HandleDesertersRunningAway()
      {
        Vec2 vec2 = this._deserterMobileParty.Position2D - MobileParty.MainParty.Position2D;
        double num1 = (double) vec2.Normalize();
        float num2 = this._deserterMobileParty.Speed * 1.5f;
        Vec2 point1 = this._deserterMobileParty.Position2D + vec2 * num2;
        float distance;
        Vec2 betweenPointAndParty = this.FindFreePositionBetweenPointAndParty(this._deserterMobileParty, in point1, out distance);
        PathFaceRecord faceIndex = Campaign.Current.MapSceneWrapper.GetFaceIndex(betweenPointAndParty);
        float angleInRadians = 0.34906584f;
        for (int index = 0; index < 10 && (faceIndex.FaceIndex == -1 || faceIndex.FaceIslandIndex == -1); ++index)
        {
          vec2.RotateCCW(angleInRadians);
          double num3 = (double) vec2.Normalize();
          betweenPointAndParty = this.FindFreePositionBetweenPointAndParty(this._deserterMobileParty, this._deserterMobileParty.Position2D + vec2 * num2, out float _);
          faceIndex = Campaign.Current.MapSceneWrapper.GetFaceIndex(betweenPointAndParty);
        }
        if ((double) distance <= 9.9999997473787516E-06)
        {
          vec2.RotateCCW((float) ((double) MBRandom.RandomInt(0, 2) * 3.1415927410125732 - 1.5707963705062866));
          Vec2 point2 = this._deserterMobileParty.Position2D + vec2 * num2;
          betweenPointAndParty = this.FindFreePositionBetweenPointAndParty(this._deserterMobileParty, in point2, out distance);
        }
        this._deserterMobileParty.Ai.SetMoveGoToPoint(betweenPointAndParty);
      }

      private void StartAmbushEncounter()
      {
        this.CreateDefenderParty();
        this._deserterMobileParty.IgnoreByOtherPartiesTill(CampaignTime.Now - CampaignTime.Hours(1f));
        EncounterManager.StartPartyEncounter(this._deserterMobileParty.Party, MobileParty.MainParty.Party);
      }

      private Vec2 FindFreePositionBetweenPointAndParty(
        MobileParty party,
        in Vec2 point,
        out float distance,
        float maxIterations = 10f,
        float acceptThres = 1E-05f,
        float maxPathDistance = 1000f,
        float euclideanThressholdFactor = 1.5f)
      {
        IMapScene mapSceneWrapper = Campaign.Current.MapSceneWrapper;
        Vec2 position2D = party.Position2D;
        PathFaceRecord faceIndex1 = mapSceneWrapper.GetFaceIndex(position2D);
        Vec2 betweenPointAndParty = position2D;
        distance = 0.0f;
        if (!PartyBase.IsPositionOkForTraveling(position2D))
        {
          Debug.FailedAssert("Origin point not valid!", "C:\\Develop\\MB3\\Source\\Bannerlord\\TaleWorlds.CampaignSystem\\Issues\\ExtortionByDesertersIssueBehavior.cs", nameof (FindFreePositionBetweenPointAndParty), 1368);
        }
        else
        {
          Vec2 vec2_1 = point;
          PathFaceRecord faceIndex2 = mapSceneWrapper.GetFaceIndex(vec2_1);
          Vec2 vec2_2 = point;
          float num1 = acceptThres * acceptThres;
          for (int index = 0; (double) index < (double) maxIterations && (double) betweenPointAndParty.DistanceSquared(point) > (double) num1 && faceIndex2.IsValid(); ++index)
          {
            float num2 = position2D.Distance(vec2_1);
            float distance1;
            if (Campaign.Current.MapSceneWrapper.GetPathDistanceBetweenAIFaces(faceIndex1, faceIndex2, position2D, vec2_1, 0.2f, maxPathDistance, out distance1) & (double) distance1 < (double) num2 * (double) euclideanThressholdFactor)
            {
              betweenPointAndParty = vec2_1;
              distance = num2;
              vec2_1 = 0.5f * (vec2_1 + vec2_2);
            }
            else
            {
              vec2_2 = vec2_1;
              vec2_1 = 0.5f * (betweenPointAndParty + vec2_2);
            }
            faceIndex2 = mapSceneWrapper.GetFaceIndex(vec2_1);
          }
        }
        return betweenPointAndParty;
      }

      private readonly struct ExtortionByDesertersQuestResult
      {
        public readonly int RenownChange;
        public readonly int HonorChange;
        public readonly float GoldMultiplier;
        public readonly int QuestGiverRelationChange;
        public readonly int QuestGiverPowerChange;
        public readonly int TownSecurityChange;
        public readonly int TownProsperityChange;
        public readonly bool IsSuccess;

        public ExtortionByDesertersQuestResult(
          int renownChange,
          int honorChange,
          float goldMultiplier,
          int questGiverRelationChange,
          int questGiverPowerChange,
          int townSecurityChange,
          int townProsperityChange,
          bool isSuccess)
        {
          this.RenownChange = renownChange;
          this.HonorChange = honorChange;
          this.GoldMultiplier = goldMultiplier;
          this.QuestGiverRelationChange = questGiverRelationChange;
          this.QuestGiverPowerChange = questGiverPowerChange;
          this.TownSecurityChange = townSecurityChange;
          this.TownProsperityChange = townProsperityChange;
          this.IsSuccess = isSuccess;
        }
      }

      internal enum ExtortionByDesertersQuestState
      {
        DesertersMovingToSettlement,
        DesertersRunningAwayFromPlayer,
        DesertersDefeatedPlayer,
        DesertersAreDefeated,
      }
    }

    public class ExtortionByDesertersIssueBehaviorTypeDefiner : SaveableTypeDefiner
    {
      public ExtortionByDesertersIssueBehaviorTypeDefiner()
        : base(490000)
      {
      }

      protected override void DefineClassTypes()
      {
        this.AddClassDefinition(typeof (ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssue), 1);
        this.AddClassDefinition(typeof (ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest), 2);
      }

      protected override void DefineEnumTypes()
      {
        this.AddEnumDefinition(typeof (ExtortionByDesertersIssueBehavior.ExtortionByDesertersIssueQuest.ExtortionByDesertersQuestState), 3);
      }
    }
  }
}
